#include <QString>
#include <sys/time.h>
#include <osip2/osip.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <QCryptographicHash>
#include "sip-server.h"
#include "sip-server-cfg.h"
#include "comm-func.h"
#include "osip_message_parse.h"

#define HK_USER_AGENT ("HKAgent v250728")

std::string gstr_call_id = "";

sip_server::sip_server()
{
    mstr_register_dev_map.clear();
    mst_dev_basic_info.clear();
    mst_dev_catalog_map.clear();
    mst_cmd_play_realtime_map.clear();
    mst_cmd_play_back_map.clear();
    mst_cmd_play_download_map.clear();
}

sip_server::~sip_server()
{

}

bool sip_server::server_start_equipment()
{
    std::string str_sip_id("");
    std::string str_sip_domain("");
    std::string str_sip_host("");
    unsigned short us_sip_port = 0;
    std::string str_sip_password("");
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_cfg(str_sip_id, str_sip_domain, str_sip_host, us_sip_port, str_sip_password);

    if(mp_ectx_equipment != nullptr){
        return false;
    }

    mp_ectx_equipment = eXosip_malloc();
    int i_ret = eXosip_init(mp_ectx_equipment);
    if(i_ret != OSIP_SUCCESS){
        printf("eXosip_init failed, return false!\n");
        return false;
    }

    i_ret = eXosip_listen_addr(mp_ectx_equipment, IPPROTO_UDP, NULL, us_sip_port, AF_INET, 0);
    //i_ret = eXosip_listen_addr(mp_ectx_equipment, IPPROTO_TCP, NULL, us_sip_port, AF_INET, 0);
    if(i_ret != OSIP_SUCCESS){
        printf("eXosip_listen_addr failed.\n");
        return false;
    }

    mpt_event_thread = new std::thread(&sip_server::hk_eXosip_processEvent_subordinate_equipment, this);

    mp_task_thread = new HHAThread::TaskThread();
    mp_task_thread->begin(1);
    mp_task_thread->set_timer(timer_check_device_online, 10 * 1000, timer_check_device_online_func, this);

#ifdef DEBUG_TEST
    mp_task_thread->set_timer(timer_debug, 60 * 1000, timer_send_playback_control_func, this);
#endif

    return true;
}

bool sip_server::set_register_callback(on_device_register_cb p_cb_fun, void *p_user)
{
    mo_register_callback_mutex.lock();
    mp_register_cb_func = p_cb_fun;
    mp_register_cb_user = p_user;
    mo_register_callback_mutex.unlock();

    return true;
}

bool sip_server::set_device_info_callback(on_device_info_cb p_cb_fun, void *p_user)
{
    mo_device_info_callback_mutex.lock();
    mp_device_info_cb_func = p_cb_fun;
    mp_device_info_cb_user = p_user;
    mo_device_info_callback_mutex.unlock();

    return true;
}

bool sip_server::set_catalog_callback(on_device_catalog_cb p_cb_fun, void *p_user)
{
    mo_catalog_callback_mutex.lock();
    mp_catalog_cb_func = p_cb_fun;
    mp_catalog_cb_user = p_user;
    mo_catalog_callback_mutex.unlock();

    return true;
}

bool sip_server::set_device_status_callback(on_device_status_cb p_cb_fun, void *p_user)
{
    mo_device_status_callback_mutex.lock();
    mp_device_status_cb_func = p_cb_fun;
    mp_device_info_cb_user = p_user;
    mo_device_status_callback_mutex.unlock();

    return true;
}

bool sip_server::set_device_info_callback(on_device_info_cb p_cb_fun, void *p_user)
{
    mo_device_info_callback_mutex.lock();
    mp_device_info_cb_func = p_cb_fun;
    mp_device_info_cb_user = p_user;
    mo_device_info_callback_mutex.unlock();

    return true;
}

bool sip_server::set_device_status_callback(on_device_status_cb p_cb_fun, void *p_user)
{
    mo_device_status_callback_mutex.lock();
    mp_device_status_cb_func = p_cb_fun;
    mp_device_status_cb_user = p_user;
    mo_device_status_callback_mutex.unlock();

    return true;
}

bool sip_server::set_invite_callback(on_device_channel_invite_cb p_cb_fun, void *p_user)
{
    mo_invite_callback_mutex.lock();
    mp_invite_cb_func = p_cb_fun;
    mp_invite_cb_user = p_user;
    mo_invite_callback_mutex.unlock();

    return true;
}

bool sip_server::set_recordinfo_callback(on_device_recordinfo_cb p_cb_fun, void *p_user)
{
    mo_record_info_callback_mutex.lock();
    mp_record_info_cb_func = p_cb_fun;
    mp_record_info_cb_user = p_user;
    mo_record_info_callback_mutex.unlock();

    return true;
}

bool sip_server::set_presetlists_callback(on_device_presetlist_cb p_cb_fun, void *p_user)
{
    mo_preset_list_callback_mutex.lock();
    mp_preset_list_cb_func = p_cb_fun;
    mp_preset_list_cb_user = p_user;
    mo_preset_list_callback_mutex.unlock();

    return true;
}

unsigned long long sip_server::get_sn()
{
    std::lock_guard<std::mutex> guard(mo_sn_mutex);
    return ++mull_sn;
}

void sip_server::send_unauthorized_response(eXosip_t *ctx, int tid, std::string &str_realm)
{
    // 1. 构建401响应
    osip_message_t *resp;
    if (eXosip_message_build_answer(ctx, tid, 401, &resp) != OSIP_SUCCESS) {
        fprintf(stderr, "构建401响应失败！\n");
        return;
    }

    // 2. 生成随机nonce（防止重放攻击）
    char nonce[32];
    snprintf(nonce, sizeof(nonce), "%lx%lx", (unsigned long)time(NULL), (unsigned long)rand());

    // 3. 设置WWW-Authenticate头（osip2 5.3.0语法）
    char auth_header[256];
    snprintf(auth_header, sizeof(auth_header),
        "Digest realm=\"%s\", nonce=\"%s\", algorithm=MD5", str_realm.c_str(), nonce);

    fprintf(stdout, "send_unauthorized_response %s\n", auth_header);

    if (osip_message_set_header(resp, "WWW-Authenticate", auth_header) != OSIP_SUCCESS) {
        fprintf(stderr, "设置WWW-Authenticate头失败！\n");
        osip_message_free(resp);
        return;
    }

    // 4. 可选：添加其他头字段
    //osip_message_set_header(resp, "Content-Length", "0");

    // 5. 发送响应（注意：resp会被eXosip自动释放）
    int i_ret = eXosip_message_send_answer(ctx, tid, 401, resp);
    if ( i_ret != OSIP_SUCCESS) {
        //eXosip_message_send_answer 会接管 resp 对象的内存释放，无需手动调用 osip_message_free,但若发送失败，需手动调用        
        if((i_ret == OSIP_BADPARAMETER) && (resp != nullptr)){
            osip_message_free(resp);
        }
        fprintf(stderr, "发送401响应失败！\n");
    } else {
        printf("已发送401质询，nonce: %s\n", nonce);
    }

    return;
}

bool sip_server::add_register_dev(std::string &str_deviceid)
{
    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    mstr_register_dev_map[str_deviceid] = time(nullptr);
    return true;
}

bool sip_server::del_register_dev(std::string &str_deviceid)
{
    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    std::map<std::string, time_t>::iterator it = mstr_register_dev_map.find(str_deviceid);
    if( it == mstr_register_dev_map.end()){
        return true;
    }

    mstr_register_dev_map.erase(it);
    return true;
}

bool sip_server::check_register_status(std::string &str_deviceid)
{
    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    std::map<std::string, time_t>::iterator it = mstr_register_dev_map.find(str_deviceid);
    if( it == mstr_register_dev_map.end()){
        return false;
    }

    return true;
}

bool sip_server::set_basic_info(std::string &str_deviceid, st_req_basicinfo &st_info)
{
    std::string str_key = str_deviceid + "-" + str_deviceid;

    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    mst_dev_basic_info[str_key] = st_info;

    return true;
}

bool sip_server::set_basic_info_by_catalog(std::string &str_device_id, Catalog_Response &st_catalog)
{
    std::string str_dev_key = str_device_id + "-" + str_device_id;
    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_dev_key);
    if( it == mst_dev_basic_info.end()){
        return false;
    }

    st_req_basicinfo st_info = it->second;

    for(int i_index = 0; i_index < st_catalog.st_channel_vec.size(); ++i_index){
        std::string str_channel_id = st_catalog.st_channel_vec[i_index].str_device_channel_id;
        if(str_channel_id != str_device_id){
            memset(st_info.pc_device_channel_id, 0x0, 32);
            memcpy(st_info.pc_device_channel_id, str_channel_id.c_str(), str_channel_id.length());

            std::string str_to = st_info.pc_to;
            std::string::size_type npos = str_to.find("@");
            if(npos != std::string::npos){
                std::string str_replace_to = "sip:" + str_channel_id + str_to.substr(npos);
                memset(st_info.pc_to, 0x0, 64);
                memcpy(st_info.pc_to, str_replace_to.c_str(), str_replace_to.length());
            }

            std::string str_key = str_device_id + "-" + str_channel_id;
            mst_dev_basic_info[str_key] = st_info;
        }
    }

    return true;
}

bool sip_server::get_basic_info(std::string &str_deviceid, st_req_basicinfo &st_info)
{
    std::lock_guard<std::mutex> guard(mo_register_dev_mutex);
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_deviceid);
    if( it == mst_dev_basic_info.end()){
        return false;
    }

    st_info = it->second;
    return true;
}

bool sip_server::set_catalog_info(std::string &str_device_id, Catalog_Response &st_catalog)
{
    std::lock_guard<std::mutex> guard(mo_device_catalog_mutex);
    std::map<std::string, Catalog_Response>::iterator it = mst_dev_catalog_map.find(str_device_id);
    if(it == mst_dev_catalog_map.end()){
        mst_dev_catalog_map[str_device_id] = st_catalog;
        return true;
    }

    Catalog_Response st_catalog_history = it->second;
    int i_his_size = st_catalog_history.st_channel_vec.size();
    std::vector<Device_Channel>::iterator it_item = st_catalog.st_channel_vec.begin();
    for(; it_item != st_catalog.st_channel_vec.end(); ++it_item){
        Device_Channel st_channel_item = *it_item;

        bool b_find = false;
        for(int i_index = 0; i_index < i_his_size; ++i_index ){
            Device_Channel st_channel_item_his = st_catalog_history.st_channel_vec[i_index];
            if(st_channel_item.str_device_channel_id == st_channel_item_his.str_device_channel_id){
                b_find = true;
                break;
            }
        }

        if(!b_find){
            st_catalog_history.st_channel_vec.push_back(st_channel_item);
        }
    }

    mst_dev_catalog_map[str_device_id] = st_catalog_history;
    return true;
}

bool sip_server::set_invite_realtime_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    mst_cmd_play_realtime_map[str_call_id] = st_id;

    return true;
}

bool sip_server::get_invite_realtime_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_realtime_map.find(str_call_id);
    if(it == mst_cmd_play_realtime_map.end()){
        return false;
    }

    st_id = it->second;
    return true;
}

bool sip_server::del_invite_realtime_cmdplay(std::string &str_call_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_realtime_map.find(str_call_id);
    if(it == mst_cmd_play_realtime_map.end()){
        return false;
    }

    mst_cmd_play_realtime_map.erase(it);
    return true;
}

bool sip_server::set_invite_playback_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    mst_cmd_play_back_map[str_call_id] = st_id;

    return true;
}

bool sip_server::get_invite_playback_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_back_map.find(str_call_id);
    if(it == mst_cmd_play_back_map.end()){
        return false;
    }

    st_id = it->second;
    return true;
}

bool sip_server::del_invite_playback_cmdplay(std::string &str_call_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_back_map.find(str_call_id);
    if(it == mst_cmd_play_back_map.end()){
        return false;
    }

    mst_cmd_play_back_map.erase(it);
    return true;
}

bool sip_server::set_invite_download_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    mst_cmd_play_download_map[str_call_id] = st_id;

    return true;
}

bool sip_server::get_invite_download_cmdplay(std::string &str_call_id, Cmd_Play &st_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_download_map.find(str_call_id);
    if(it == mst_cmd_play_download_map.end()){
        return false;
    }

    st_id = it->second;
    return true;
}

bool sip_server::del_invite_download_cmdplay(std::string &str_call_id)
{
    std::lock_guard<std::mutex> guard(mo_invite_mutex);
    std::map<std::string, Cmd_Play>::iterator it = mst_cmd_play_download_map.find(str_call_id);
    if(it == mst_cmd_play_download_map.end()){
        return false;
    }

    mst_cmd_play_download_map.erase(it);
    return true;
}

bool sip_server::post_request_catalog(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_catalog;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_deviceinfo(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_device_info;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_devicestatus(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_device_status;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_recordinfo(std::string &str_device_id, std::string &str_start_time, std::string &str_end_time)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_query_recordinfo *p_req = new st_req_query_recordinfo;
    p_req->st_req_url = st_base_url;
    memcpy(p_req->pc_start_time, str_start_time.c_str(), str_start_time.length());
    memcpy(p_req->pc_end_time, str_end_time.c_str(), str_end_time.length());

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_device_recordinfo;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_alarm(std::string &str_device_id, std::string &str_start_time, std::string &str_end_time)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_query_alarm *p_req = new st_req_query_alarm;
    p_req->st_req_url = st_base_url;
    memcpy(p_req->pc_start_time, str_start_time.c_str(), str_start_time.length());
    memcpy(p_req->pc_end_time, str_end_time.c_str(), str_end_time.length());

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_device_alarm;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_configdownload(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_configdownload;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_request_presetlist(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_request_preset_list;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_subscribe_catalog(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    mo_register_dev_mutex.lock();
    st_req_basicinfo *p_req = nullptr;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        p_req = new st_req_basicinfo;
        st_req_basicinfo st_info = it->second;
        memcpy(p_req, &st_info, sizeof(st_info));
    }
    mo_register_dev_mutex.unlock();

    if(p_req == nullptr){
        return false;
    }

    HHAThread::CallBackStruct st;
    st.callback_func = to_subscribe_catalog;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_ptz(std::string &str_device_id, int i_ptz_cmd)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_ptz *p_req = new st_req_control_ptz;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_ptz_cmd;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_ptz;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_ptz_preset(std::string &str_device_id, int i_cmd, int i_preset)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_ptz_preset *p_req = new st_req_control_ptz_preset;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_cmd;
    p_req->i_preset_no = i_preset;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_ptz_preset;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_visual_zoom(std::string &str_device_id, std::string &str_device_channel_id, int i_cmd)
{
    std::string str_key = str_device_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_ptz *p_req = new st_req_control_ptz;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_cmd;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_visual_zoom;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_visual_focus_iris(std::string &str_device_id, std::string &str_device_channel_id, int i_cmd)
{
    std::string str_key = str_device_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_ptz *p_req = new st_req_control_ptz;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_cmd;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_visual_focus_iris;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_teleboot(std::string &str_device_id)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_basicinfo *p_req = new st_req_basicinfo;
    *p_req = st_base_url;


    HHAThread::CallBackStruct st;
    st.callback_func = to_control_teleboot;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_record(std::string &str_device_id, int i_cmd)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_record *p_req = new st_req_control_record;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_cmd;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_record;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_control_guard(std::string &str_device_id, int i_cmd)
{
    std::string str_key = str_device_id + "-" + str_device_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_req_control_guard *p_req = new st_req_control_guard;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = i_cmd;

    HHAThread::CallBackStruct st;
    st.callback_func = to_control_guard;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_play(std::string &str_dev_id, std::string &str_device_channel_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_play_realtime *p_req = new st_invite_play_realtime;
    p_req->st_req_url = st_base_url;
    p_req->str_device_id = str_dev_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_play;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_bye(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_bye *p_req = new st_invite_bye;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = 1;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_bye;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_start_time, std::string &str_end_time)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback *p_req = new st_invite_playback;
    p_req->st_req_url = st_base_url;
    p_req->str_device_id = str_dev_id;
    memcpy(p_req->pc_start_time, str_start_time.c_str(), str_start_time.length());
    memcpy(p_req->pc_end_time, str_end_time.c_str(), str_end_time.length());

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_playback;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback_pause(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback_pause *p_req = new st_invite_playback_pause;
    p_req->st_req_url = st_base_url;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_playback_pause;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback_continue(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback_pause *p_req = new st_invite_playback_pause;
    p_req->st_req_url = st_base_url;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_playback_continue;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback_scale(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id, float f_scale)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback_scale *p_req = new st_invite_playback_scale;
    p_req->st_req_url = st_base_url;
    p_req->str_call_id = str_call_id;
    p_req->f_scale = f_scale;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_playback_scale;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback_teardown(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback_teardown *p_req = new st_invite_playback_teardown;
    p_req->st_req_url = st_base_url;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_playback_teardown;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_playback_bye(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_bye *p_req = new st_invite_bye;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = 2;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_bye;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_download(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_start_time, std::string &str_end_time)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_playback *p_req = new st_invite_playback;
    p_req->st_req_url = st_base_url;
    p_req->str_device_id = str_dev_id;
    memcpy(p_req->pc_start_time, str_start_time.c_str(), str_start_time.length());
    memcpy(p_req->pc_end_time, str_end_time.c_str(), str_end_time.length());

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_download;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

bool sip_server::post_invite_download_bye(std::string &str_dev_id, std::string &str_device_channel_id, std::string &str_call_id)
{
    std::string str_key = str_dev_id + "-" + str_device_channel_id;
    bool b_find_base_url = false;
    mo_register_dev_mutex.lock();
    st_req_basicinfo st_base_url;
    std::map<std::string, st_req_basicinfo>::iterator it = mst_dev_basic_info.find(str_key);
    if(it != mst_dev_basic_info.end()){
        st_base_url = it->second;
        b_find_base_url = true;
    }
    mo_register_dev_mutex.unlock();

    if(!b_find_base_url){
        return false;
    }

    st_invite_bye *p_req = new st_invite_bye;
    p_req->st_req_url = st_base_url;
    p_req->i_cmd = 3;
    p_req->str_call_id = str_call_id;

    HHAThread::CallBackStruct st;
    st.callback_func = to_invite_bye;
    st.arg = this;
    st.arg_second = p_req;

    mo_task_thread_mutex.lock();
    mp_task_thread->post_task(st);
    mo_task_thread_mutex.unlock();

    return true;
}

void sip_server::to_request_catalog(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];    

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);

    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_catalog Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // Catalog请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>Catalog</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Catalog request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_device_info(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_device_info Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // DeviceInfo请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>DeviceInfo</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Catalog request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_device_status(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_device_status Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // DeviceStatus请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>DeviceStatus</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceStatus request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_preset_list(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_preset_list Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // DeviceStatus请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>PresetQuery</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceStatus request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_device_recordinfo(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_query_recordinfo *p_para = (st_req_query_recordinfo *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_device_recordinfo Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // DeviceStatus请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>RecordInfo</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <StartTime>%s</StartTime>\r\n"
        "  <EndTime>%s</EndTime>\r\n"
        "  <Type>all</Type>\r\n"
        "</Query>";
    //<Type>: time/alarm/manual/all

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), p_para->pc_start_time, p_para->pc_end_time);
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceStatus request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_device_alarm(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_query_alarm *p_para = (st_req_query_alarm *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_device_alarm Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // DeviceStatus请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>Alarm</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <StartAlarmPriority>0</StartAlarmPriority>"
        "  <EndAlarmPriority>0</EndAlarmPriority>"
        "  <AlarmMethod>0</AlarmMethod>"
        "  <StartAlarmTime>%s</StartAlarmTime>\r\n"
        "  <EndAlarmTime>%s</EndAlarmTime>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), p_para->pc_start_time, p_para->pc_end_time);
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceStatus request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_request_configdownload(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_request_configdownload Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // Catalog请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>ConfigDownload</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Catalog request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_subscribe_catalog(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_basicinfo *p_para = (st_req_basicinfo *)p_arg_second;

    std::string str_from(p_para->pc_from);
    std::string str_to(p_para->pc_to);
    std::string str_device_id(p_para->pc_device_channel_id);
    std::string str_device_ip(p_para->pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_subscribe_build_initial_request(p_this->mp_ectx_equipment, &message, str_to.c_str(), str_from.c_str(), request_uri.c_str(), "presence", 3600);
    //ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "SUBSCRIBE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_subscribe_catalog Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);
    // Catalog请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Query>\r\n"
        "  <CmdType>Catalog</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "</Query>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    int i_sid = eXosip_subscribe_send_initial_request(p_this->mp_ectx_equipment, message);
    //ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);

    printf("Sent Catalog Subscribe to %s, sid is %d\n", str_device_id.c_str(), i_sid);
    delete p_para;
    return;
}

void sip_server::to_control_ptz(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_ptz *p_para = (st_req_control_ptz *)p_arg_second;
    if(p_para->i_cmd < 0 || p_para->i_cmd > 8){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_ptz Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_cmd = "A50F01";
    switch(p_para->i_cmd){
    case 0:{
        str_cmd += "08008100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x08 + 0x00 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 1:{
        str_cmd += "04008100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x04 + 0x00 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 2:{
        str_cmd += "02810000";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x02 + 0x81 + 0x00 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 3:{
        str_cmd += "01810000";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x01 + 0x81 + 0x00 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 4:{
        str_cmd += "0A818100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x0A + 0x81 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 5:{
        str_cmd += "09818100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x09 + 0x81 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 6:{
        str_cmd += "06818100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x06 + 0x81 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 7:{
        str_cmd += "05818100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x05 + 0x81 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 8:{
        str_cmd += "00000000";
        int i_crc = 0xA5 + 0x0F + 0x01;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    default:
        break;
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <PTZCmd>%s</PTZCmd>\r\n"
        "  <Info>\r\n"
        "    <ControlPriority>5</ControlPriority>\r\n"
        "  </Info>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl PTZCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_ptz_preset(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_ptz_preset *p_para = (st_req_control_ptz_preset *)p_arg_second;
    if(p_para->i_cmd < 1 || p_para->i_cmd > 3){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);

    std::string str_preset_no = int_to_hex(p_para->i_preset_no);
    if(p_para->i_preset_no < 10){
        str_preset_no = "0" + str_preset_no;
    }

    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_ptz_preset Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_cmd = "A50F01";
    switch(p_para->i_cmd){
    case 1:{
        //set
        str_cmd += "8100";
        str_cmd += str_preset_no;
        str_cmd += "00";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x81 + 0x00 + p_para->i_preset_no + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 2:{
        //goto
        str_cmd += "8200";
        str_cmd += str_preset_no;
        str_cmd += "00";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x82 + 0x00 + p_para->i_preset_no + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 3:{
        //del
        str_cmd += "8300";
        str_cmd += str_preset_no;
        str_cmd += "00";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x83 + 0x00 + p_para->i_preset_no + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    default:
        break;
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <PTZCmd>%s</PTZCmd>\r\n"
        "  <Info>\r\n"
        "    <ControlPriority>5</ControlPriority>\r\n"
        "  </Info>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl PTZCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_visual_zoom(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_ptz *p_para = (st_req_control_ptz *)p_arg_second;
    if(p_para->i_cmd < 0 || p_para->i_cmd > 2){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_visual_zoom Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_cmd = "A50F01";
    switch(p_para->i_cmd){
    case 0:{
        str_cmd += "00000000";
        int i_crc = 0xA5 + 0x0F + 0x01;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 1:{
        str_cmd += "10000010";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x10 + 0x00 + 0x00 + 0x10;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 2:{
        str_cmd += "20000010";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x20 + 0x00 + 0x00 + 0x10;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    default:
        break;
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <PTZCmd>%s</PTZCmd>\r\n"
        "  <Info>\r\n"
        "    <ControlPriority>5</ControlPriority>\r\n"
        "  </Info>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl PTZCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_visual_focus_iris(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_ptz *p_para = (st_req_control_ptz *)p_arg_second;
    if(p_para->i_cmd < 0 || p_para->i_cmd > 2){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_visual_focus_iris Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_cmd = "A50F01";
    switch(p_para->i_cmd){
    case 0:{
        str_cmd += "40000000";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x40;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 1:{
        str_cmd += "42810000";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x42 + 0x81 + 0x00 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 2:{
        str_cmd += "41810000";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x41 + 0x81 + 0x00 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 3:{
        str_cmd += "48008100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x48 + 0x00 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    case 4:{
        str_cmd += "41008100";
        int i_crc = 0xA5 + 0x0F + 0x01 + 0x41 + 0x00 + 0x81 + 0x00;
        i_crc = i_crc % 0x100;
        std::string str_crc = int_to_hex(i_crc);
        str_cmd += str_crc;
        break;
    }
    default:
        break;
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <PTZCmd>%s</PTZCmd>\r\n"
        "  <Info>\r\n"
        "    <ControlPriority>5</ControlPriority>\r\n"
        "  </Info>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl PTZCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_teleboot(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_ptz *p_para = (st_req_control_ptz *)p_arg_second;
    if(p_para->i_cmd < 0 || p_para->i_cmd > 2){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_teleboot Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    // TeleBoot请求内容（GB28181格式）
    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <TeleBoot>Boot</TeleBoot>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl TeleBoot request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_record(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_record *p_para = (st_req_control_record *)p_arg_second;
    if(p_para->i_cmd < 1 || p_para->i_cmd > 2){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_record Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_record_cmd;
    if(p_para->i_cmd == 1){
        str_record_cmd = "Record";
    } else {
        str_record_cmd = "StopRecord";
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <RecordCmd>%s</RecordCmd>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_record_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl RecordCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_control_guard(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_req_control_guard *p_para = (st_req_control_guard *)p_arg_second;
    if(p_para->i_cmd < 1 || p_para->i_cmd > 2){
        delete p_para;
        return;
    }

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *message = NULL;
    int ret;
    char tmp[1024];

    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_build_request(p_this->mp_ectx_equipment, &message, "MESSAGE", str_to.c_str(), str_from.c_str(), request_uri.c_str());
    eXosip_unlock(p_this->mp_ectx_equipment);


    if (ret != 0 || message == NULL) {
        delete p_para;
        fprintf(stderr, "to_control_guard Failed to build MESSAGE request\n");
        return;
    }

    // 设置消息内容
    osip_message_set_content_type(message, "Application/MANSCDP+xml");
    osip_message_replace_header(message, "User-Agent", HK_USER_AGENT);

    std::string str_guard_cmd;
    if(p_para->i_cmd == 1){
        str_guard_cmd = "SetGuard";
    } else {
        str_guard_cmd = "ResetGuard";
    }

    const char *body =
        "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"
        "<Control>\r\n"
        "  <CmdType>DeviceControl</CmdType>\r\n"
        "  <SN>%lld</SN>\r\n"
        "  <DeviceID>%s</DeviceID>\r\n"
        "  <GuardCmd>%s</GuardCmd>\r\n"
        "</Control>";

    unsigned long long ull_sn = p_this->get_sn();
    snprintf(tmp, sizeof(tmp), body, ull_sn, str_device_id.c_str(), str_guard_cmd.c_str());
    osip_message_set_body(message, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_message_send_request(p_this->mp_ectx_equipment, message);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(message);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent DeviceControl GuardCmd request to %s\n", str_device_id.c_str());
    delete p_para;
    return;
}

void sip_server::to_invite_play(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_play_realtime *p_para = (st_invite_play_realtime *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_channel_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_channel_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *invite = NULL;
    int ret;
    char tmp[1024];

    //int eXosip_call_build_initial_invite (struct eXosip_t *excontext, osip_message_t ** invite, const char *to, const char *from, const char *route, const char *subject);
    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_build_initial_invite(p_this->mp_ectx_equipment, &invite, str_to.c_str(), str_from.c_str(), request_uri.c_str(), NULL);
    eXosip_unlock(p_this->mp_ectx_equipment);

    if (ret != 0 || invite == NULL) {
        delete p_para;
        fprintf(stderr, "to_invite_play Failed to build MESSAGE request\n");
        return;
    }

    p_this->mo_invite_mutex.lock();
    unsigned int ui_invite_y = p_this->mui_invite_y++;
    p_this->mo_invite_mutex.unlock();
    std::string str_invite_y = std::to_string(ui_invite_y);
    if(str_invite_y.size() < 10){
        str_invite_y = "0" + str_invite_y;
    }

    std::string str_sip_id;
    std::string str_sip_domain;
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_sip_info(str_sip_id, str_sip_domain);
    //SubJect->媒体流发送者ID:发送方媒体流序列号，媒体流接收者ID:接收方媒体流序列号
    std::string str_subject = str_device_channel_id + ":" + str_invite_y + "," + str_sip_id + ":0";
    osip_message_set_subject(invite, str_subject.c_str());

    // 设置消息内容
    osip_message_set_content_type(invite, "Application/sdp");
    osip_message_replace_header(invite, "User-Agent", HK_USER_AGENT);

    const char *body =
            "v=0\r\n"
            "o=%s 0 0 IN IP4 %s\r\n"
            "s=Play\r\n"
            "c=IN IP4 %s\r\n"
            "t=0 0\r\n"
            "m=video %d RTP/AVP 96\r\n"
            "a=recvonly\r\n"
            "a=rtpmap:96 PS/90000\r\n"
            "a=rtpmap:97 MPEG4/90000\r\n"
            "a=rtpmap:98 H264/90000\r\n"
            "y=%s\r\n";
//            "a=setup:passive\r\n"
//            "a=connection:new\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.116:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    std::string str_media_server_ip;
    unsigned short us_media_server_port;
    singleton_lock_sip_server_cfg_handler::Instance()->get_media_server_cfg(str_media_server_ip, us_media_server_port);

    snprintf(tmp, sizeof(tmp), body, str_device_channel_id.c_str(), str_media_server_ip.c_str(), str_media_server_ip.c_str(), us_media_server_port, str_invite_y.c_str());

    osip_message_set_body(invite, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_send_initial_invite(p_this->mp_ectx_equipment, invite);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(invite);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    std::string str_call_id("");
    osip_call_id *pt_callid_ = osip_message_get_call_id(invite);
    if(pt_callid_->number != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->number);
        str_call_id = pt_callid_->number;
    }
    if(pt_callid_->host != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->host);
    }

    printf("Sent Invite Play request to %s, body is %s\n", str_device_channel_id.c_str(), tmp);

    st_dev_channel_id st;
    st.str_device_id = p_para->str_device_id;
    st.str_channel_id = p_para->st_req_url.pc_device_channel_id;

    if(!str_call_id.empty()){
        p_this->mo_invite_mutex.lock();
        p_this->mst_callid_to_dev_channel_id[str_call_id] = st;
        p_this->mo_invite_mutex.unlock();
    }

    //mst_callid_to_dev_channel_id
    delete p_para;
    return;
}

void sip_server::to_invite_playback(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback *p_para = (st_invite_playback *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *invite = NULL;
    int ret;
    char tmp[1024];

    //int eXosip_call_build_initial_invite (struct eXosip_t *excontext, osip_message_t ** invite, const char *to, const char *from, const char *route, const char *subject);
    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_build_initial_invite(p_this->mp_ectx_equipment, &invite, str_to.c_str(), str_from.c_str(), request_uri.c_str(), NULL);
    eXosip_unlock(p_this->mp_ectx_equipment);

    if (ret != 0 || invite == NULL) {
        delete p_para;
        fprintf(stderr, "to_invite_playback Failed to build MESSAGE request\n");
        return;
    }

    p_this->mo_invite_mutex.lock();
    unsigned int ui_invite_y = p_this->mui_invite_y++;
    p_this->mo_invite_mutex.unlock();
    std::string str_invite_y = std::to_string(ui_invite_y);
    if(str_invite_y.size() < 10){
        str_invite_y = "1" + str_invite_y;
    }

    std::string str_sip_id;
    std::string str_sip_domain;
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_sip_info(str_sip_id, str_sip_domain);
    //SubJect->媒体流发送者ID:发送方媒体流序列号，媒体流接收者ID:接收方媒体流序列号
    std::string str_subject = str_device_id + ":" + str_invite_y + "," + str_sip_id + ":0";
    osip_message_set_subject(invite, str_subject.c_str());

    // 设置消息内容
    osip_message_set_content_type(invite, "Application/sdp");
    osip_message_replace_header(invite, "User-Agent", HK_USER_AGENT);

    const char *body =
            "v=0\r\n"
            "o=%s 0 0 IN IP4 %s\r\n"
            "s=Playback\r\n"
            "u=%s:0\r\n"
            "c=IN IP4 %s\r\n"
            "t=%s %s\r\n"
            "m=video %d RTP/AVP 96\r\n"
            "a=recvonly\r\n"
            "a=rtpmap:96 PS/90000\r\n"
            "a=rtpmap:97 MPEG4/90000\r\n"
            "a=rtpmap:98 H264/90000\r\n"
            "y=%s\r\n";
//            "a=setup:passive\r\n"
//            "a=connection:new\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.124:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    std::string str_media_server_ip;
    unsigned short us_media_server_port;
    singleton_lock_sip_server_cfg_handler::Instance()->get_media_server_cfg(str_media_server_ip, us_media_server_port);

    snprintf(tmp, sizeof(tmp), body, str_device_id.c_str(), str_media_server_ip.c_str(), str_device_id.c_str(), str_media_server_ip.c_str(),
             p_para->pc_start_time, p_para->pc_end_time, us_media_server_port, str_invite_y.c_str());

    osip_message_set_body(invite, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_send_initial_invite(p_this->mp_ectx_equipment, invite);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(invite);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Invite Playback request to %s, body is %s\n", str_device_id.c_str(), tmp);

    std::string str_call_id("");
    osip_call_id *pt_callid_ = osip_message_get_call_id(invite);
    if(pt_callid_->number != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->number);
        str_call_id = pt_callid_->number;
    }
    if(pt_callid_->host != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->host);
    }

    st_dev_channel_id st;
    st.str_device_id = p_para->str_device_id;
    st.str_channel_id = p_para->st_req_url.pc_device_channel_id;

    if(!str_call_id.empty()){
        p_this->mo_invite_mutex.lock();
        p_this->mst_callid_to_dev_channel_id[str_call_id] = st;
        p_this->mo_invite_mutex.unlock();
    }

    delete p_para;
    return;
}

void sip_server::to_invite_playback_pause(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback_pause *p_para = (st_invite_playback_pause *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    Cmd_Play st_play;
    bool b_ret = p_this->get_invite_playback_cmdplay(p_para->str_call_id, st_play);
    if (!b_ret) {
        delete p_para;
        fprintf(stderr, "to_invite_playback_pause Failed to build MESSAGE request\n");
        return;
    }

    // 构建MESSAGE请求
    osip_message_t *p_info = nullptr;
    eXosip_lock(p_this->mp_ectx_equipment);
    eXosip_call_build_info(p_this->mp_ectx_equipment, st_play.mi_play_did, &p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);

    // 设置消息内容
    osip_message_set_content_type(p_info, "Application/MANSRTSP");
    osip_message_replace_header(p_info, "User-Agent", HK_USER_AGENT);
    //osip_message_replace_header(p_info, "Call-ID", p_para->str_call_id.c_str());

    long cseq = time(NULL) % 1000000; // 生成CSeq序列号

    const char *body =
            "PAUSE RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "PauseTime: now\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.124:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    char tmp[1024];
    snprintf(tmp, sizeof(tmp), body, cseq);
    osip_message_set_body(p_info, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    int ret = eXosip_call_send_request(p_this->mp_ectx_equipment, st_play.mi_play_did, p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Invite Playback control to %s, body is %s\n", str_device_id.c_str(), tmp);

    delete p_para;
    return;
}

void sip_server::to_invite_playback_continue(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback_pause *p_para = (st_invite_playback_pause *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    Cmd_Play st_play;
    bool b_ret = p_this->get_invite_playback_cmdplay(p_para->str_call_id, st_play);
    if (!b_ret) {
        delete p_para;
        fprintf(stderr, "to_invite_playback_continue Failed to build MESSAGE request\n");
        return;
    }

    // 构建MESSAGE请求
    osip_message_t *p_info = nullptr;
    eXosip_lock(p_this->mp_ectx_equipment);
    eXosip_call_build_info(p_this->mp_ectx_equipment, st_play.mi_play_did, &p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);

    // 设置消息内容
    osip_message_set_content_type(p_info, "Application/MANSRTSP");
    osip_message_replace_header(p_info, "User-Agent", HK_USER_AGENT);
    //osip_message_replace_header(p_info, "Call-ID", p_para->str_call_id.c_str());

    long cseq = time(NULL) % 1000000; // 生成CSeq序列号

    const char *body =
            "PLAY RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Range: npt=now-\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.124:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    char tmp[1024];
    snprintf(tmp, sizeof(tmp), body, cseq);
    osip_message_set_body(p_info, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    int ret = eXosip_call_send_request(p_this->mp_ectx_equipment, st_play.mi_play_did, p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Invite Playback control to %s, body is %s\n", str_device_id.c_str(), tmp);

    delete p_para;
    return;
}

void sip_server::to_invite_playback_scale(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback_scale *p_para = (st_invite_playback_scale *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    Cmd_Play st_play;
    bool b_ret = p_this->get_invite_playback_cmdplay(p_para->str_call_id, st_play);
    if (!b_ret) {
        delete p_para;
        fprintf(stderr, "to_invite_playback_scale Failed to build MESSAGE request\n");
        return;
    }

    // 构建MESSAGE请求
    osip_message_t *p_info = nullptr;
    eXosip_lock(p_this->mp_ectx_equipment);
    eXosip_call_build_info(p_this->mp_ectx_equipment, st_play.mi_play_did, &p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);

    // 设置消息内容
    osip_message_set_content_type(p_info, "Application/MANSRTSP");
    osip_message_replace_header(p_info, "User-Agent", HK_USER_AGENT);
    //osip_message_replace_header(p_info, "Call-ID", p_para->str_call_id.c_str());

    long cseq = time(NULL) % 1000000; // 生成CSeq序列号

    const char *body =
            "PLAY RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Scale: %f\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.124:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    char tmp[1024];
    snprintf(tmp, sizeof(tmp), body, cseq, p_para->f_scale);
    osip_message_set_body(p_info, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    int ret = eXosip_call_send_request(p_this->mp_ectx_equipment, st_play.mi_play_did, p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Invite Playback control to %s, body is %s\n", str_device_id.c_str(), tmp);

    delete p_para;
    return;
}

void sip_server::to_invite_playback_teardown(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback_teardown *p_para = (st_invite_playback_teardown *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    Cmd_Play st_play;
    bool b_ret = p_this->get_invite_playback_cmdplay(p_para->str_call_id, st_play);
    if (!b_ret) {
        delete p_para;
        fprintf(stderr, "to_invite_playback_teardown Failed to build MESSAGE request\n");
        return;
    }

    // 构建MESSAGE请求
    osip_message_t *p_info = nullptr;
    eXosip_lock(p_this->mp_ectx_equipment);
    eXosip_call_build_info(p_this->mp_ectx_equipment, st_play.mi_play_did, &p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);

    // 设置消息内容
    osip_message_set_content_type(p_info, "Application/MANSRTSP");
    osip_message_replace_header(p_info, "User-Agent", HK_USER_AGENT);
    //osip_message_replace_header(p_info, "Call-ID", p_para->str_call_id.c_str());

    long cseq = time(NULL) % 1000000; // 生成CSeq序列号

    const char *body =
            "TEARDOWN RTSP/1.0\r\n"
            "CSeq: %d\r\n";

    //12345678->HEX:00BC614E
    //http://192.168.2.124:8001/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=rtp&schema=rtsp&scheam=00BC614E

    char tmp[1024];
    snprintf(tmp, sizeof(tmp), body, cseq);
    osip_message_set_body(p_info, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    int ret = eXosip_call_send_request(p_this->mp_ectx_equipment, st_play.mi_play_did, p_info);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);
        delete p_para;
        return;
    }

    printf("Sent Invite Playback control to %s, body is %s\n", str_device_id.c_str(), tmp);

    delete p_para;
    return;
}

void sip_server::to_invite_download(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_playback *p_para = (st_invite_playback *)p_arg_second;

    std::string str_from(p_para->st_req_url.pc_from);
    std::string str_to(p_para->st_req_url.pc_to);
    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
    std::string str_device_ip(p_para->st_req_url.pc_dev_ip);
    std::string str_device_port = std::to_string(p_para->st_req_url.ui_dev_port);
    std::string str_schema = "sip";

    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    osip_message_t *invite = NULL;
    int ret;
    char tmp[1024];

    //int eXosip_call_build_initial_invite (struct eXosip_t *excontext, osip_message_t ** invite, const char *to, const char *from, const char *route, const char *subject);
    // 构建MESSAGE请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_build_initial_invite(p_this->mp_ectx_equipment, &invite, str_to.c_str(), str_from.c_str(), request_uri.c_str(), NULL);
    eXosip_unlock(p_this->mp_ectx_equipment);

    if (ret != 0 || invite == NULL) {
        delete p_para;
        fprintf(stderr, "to_invite_download Failed to build MESSAGE request\n");
        return;
    }

    p_this->mo_invite_mutex.lock();
    unsigned int ui_invite_y = p_this->mui_invite_y++;
    p_this->mo_invite_mutex.unlock();
    std::string str_invite_y = std::to_string(ui_invite_y);
    if(str_invite_y.size() < 10){
        str_invite_y = "1" + str_invite_y;
    }

    std::string str_sip_id;
    std::string str_sip_domain;
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_sip_info(str_sip_id, str_sip_domain);
    //SubJect->媒体流发送者ID:发送方媒体流序列号，媒体流接收者ID:接收方媒体流序列号
    std::string str_subject = str_device_id + ":" + str_invite_y + "," + str_sip_id + ":0";
    osip_message_set_subject(invite, str_subject.c_str());

    // 设置消息内容
    osip_message_set_content_type(invite, "Application/sdp");
    osip_message_replace_header(invite, "User-Agent", HK_USER_AGENT);

    const char *body =
            "v=0\r\n"
            "o=%s 0 0 IN IP4 %s\r\n"
            "s=Download\r\n"
            "u=%s:0\r\n"
            "c=IN IP4 %s\r\n"
            "t=%s %s\r\n"
            "m=video %d RTP/AVP 96\r\n"
            "a=recvonly\r\n"
            "a=rtpmap:96 PS/90000\r\n"
            "a=rtpmap:97 MPEG4/90000\r\n"
            "a=rtpmap:98 H264/90000\r\n"
            "a=downloadspeed:4\r\n"
            "y=%s\r\n";

    std::string str_media_server_ip;
    unsigned short us_media_server_port;
    singleton_lock_sip_server_cfg_handler::Instance()->get_media_server_cfg(str_media_server_ip, us_media_server_port);

    snprintf(tmp, sizeof(tmp), body, str_device_id.c_str(), str_media_server_ip.c_str(), str_device_id.c_str(), str_media_server_ip.c_str(),
             p_para->pc_start_time, p_para->pc_end_time, us_media_server_port, str_invite_y.c_str());

    osip_message_set_body(invite, tmp, strlen(tmp));

    // 发送请求
    eXosip_lock(p_this->mp_ectx_equipment);
    ret = eXosip_call_send_initial_invite(p_this->mp_ectx_equipment, invite);
    eXosip_unlock(p_this->mp_ectx_equipment);
    if (ret < 0) {
        if(ret == OSIP_BADPARAMETER){
            osip_message_free(invite);
        }

        fprintf(stderr, "Failed to send MESSAGE request, ret %d\n", ret);

        delete p_para;
        return;
    }

    printf("Sent Invite Playback request to %s, body is %s\n", str_device_id.c_str(), tmp);

    std::string str_call_id("");
    osip_call_id *pt_callid_ = osip_message_get_call_id(invite);
    if(pt_callid_->number != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->number);
        str_call_id = pt_callid_->number;
    }
    if(pt_callid_->host != nullptr){
        fprintf(stdout, "Sent Invite Play request, callid number is %s\n", pt_callid_->host);
    }

    st_dev_channel_id st;
    st.str_device_id = p_para->str_device_id;
    st.str_channel_id = p_para->st_req_url.pc_device_channel_id;

    if(!str_call_id.empty()){
        p_this->mo_invite_mutex.lock();
        p_this->mst_callid_to_dev_channel_id[str_call_id] = st;
        p_this->mo_invite_mutex.unlock();
    }

    delete p_para;
    return;
}

void sip_server::to_invite_bye(void *p_arg_first, void *p_arg_second)
{
    sip_server *p_this = (sip_server *)p_arg_first;
    st_invite_bye *p_para = (st_invite_bye *)p_arg_second;

//    std::string str_from(p_para->pc_from);
//    std::string str_to(p_para->pc_to);
//    std::string str_device_id(p_para->st_req_url.pc_device_channel_id);
//    std::string str_device_ip(p_para->pc_dev_ip);
//    std::string str_device_port = std::to_string(p_para->ui_dev_port);
//    std::string str_schema = "sip";
//    std::string request_uri = str_schema + ":" + str_device_id + "@" + str_device_ip + ":" + str_device_port;

    bool b_ret = true;
    Cmd_Play st_play;
    if(p_para->i_cmd == 1){
        p_this->get_invite_realtime_cmdplay(p_para->str_call_id, st_play);
    } else if(p_para->i_cmd == 2){
        p_this->get_invite_playback_cmdplay(p_para->str_call_id, st_play);
    } else if(p_para->i_cmd == 3){
        p_this->get_invite_download_cmdplay(p_para->str_call_id, st_play);
    } else {
        b_ret = false;
    }

    if(b_ret){
        eXosip_lock(p_this->mp_ectx_equipment);
        eXosip_call_terminate(p_this->mp_ectx_equipment, st_play.mi_call_id, st_play.mi_play_did);
        eXosip_unlock(p_this->mp_ectx_equipment);
    }

    delete p_para;
    return;
}

void sip_server::timer_check_device_online_func(unsigned int ui_timer, void *arg)
{
    //如果设备注册超时，从注册表删除但不主动发送401，设备下次发送请求时再返回未认证状态
    if(ui_timer != timer_check_device_online){
        return;
    }

    sip_server *p_this = (sip_server *)arg;

    time_t st_timenow = time(nullptr);
    std::lock_guard<std::mutex> guard(p_this->mo_register_dev_mutex);
    std::map<std::string, time_t>::iterator it = p_this->mstr_register_dev_map.begin();
    for(; it != p_this->mstr_register_dev_map.end(); ){
        if(st_timenow < it->second){
            it->second = st_timenow;
        }

        if(st_timenow - it->second > 3600){
            it = p_this->mstr_register_dev_map.erase(it);
        } else {
            it++;
        }
    }

    return;
}

#ifdef DEBUG_TEST
void sip_server::timer_send_playback_control_func(unsigned int ui_timer, void *arg)
{
    if(ui_timer != timer_debug){
        return;
    }

    sip_server *p_this = (sip_server *)arg;
    std::string str_device_id = "34020000001320000001";
    std::string str_channel_id = "34020000001320000001";
    std::string str_call_id = gstr_call_id;

    p_this->post_invite_bye(str_device_id, str_channel_id, str_call_id);
    //p_this->post_invite_playback_scale(str_device_id, str_channel_id, str_call_id, 4.0);

    return;
}
#endif

void sip_server::hk_eXosip_processEvent_subordinate_equipment()
{
    std::string str_sip_id("");
    std::string str_sip_domain("");
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_sip_info(str_sip_id, str_sip_domain);

    std::string str_passwd("");
    singleton_lock_sip_server_cfg_handler::Instance()->get_sip_server_unified_access_password(str_passwd);

    eXosip_event_t *p_event = NULL;  // msg event
    osip_message_t *p_answer = NULL; // ack

    osip_message_t *psss = NULL;
    while(!mb_thread_fini){
        p_event = eXosip_event_wait( mp_ectx_equipment, 0, 200 );

//        eXosip_lock( mp_ectx_equipment );
//        eXosip_default_action( mp_ectx_equipment, p_event );
//        eXosip_automatic_action( mp_ectx_equipment );
//        eXosip_unlock( mp_ectx_equipment );

        if(p_event == nullptr){
            osip_usleep( 10000 );
            continue;
        }

        switch(p_event->type){
        case EXOSIP_MESSAGE_NEW:
        {
            fprintf(stdout, "EXOSIP_MESSAGE_NEW call_id is %d, did is %d\n", p_event->cid, p_event->did);
            const char *username = p_event->request->from->url->username;
            const char *sip_method = p_event->request->sip_method;
            std::string str_username(username);

            if( MSG_IS_MESSAGE(p_event->request) ){

                eXosip_lock( mp_ectx_equipment );
                eXosip_message_build_answer( mp_ectx_equipment, p_event->tid, 200, &p_answer );
                eXosip_message_send_answer( mp_ectx_equipment, p_event->tid, 200, p_answer );
                eXosip_unlock( mp_ectx_equipment );                

                if(!check_register_status(str_username)){
                    eXosip_lock(mp_ectx_equipment);
                    send_unauthorized_response(mp_ectx_equipment, p_event->tid, str_sip_domain);
                    eXosip_unlock(mp_ectx_equipment);

                    printf("设备 %s 需要重新注册\n", username);

                    break;
                }

                char *s;
                size_t len;
                osip_message_to_str(p_event->request, &s, &len);
                fprintf(stdout, "EXOSIP_MESSAGE_NEW request msg is:\n%s\n", s);
                delete []s;

                //接收到新消息
                osip_body_t *p_msg_body = NULL;
                osip_message_get_body( p_event->request, 0, &p_msg_body );

                osip_call_id *pt_callid_ = osip_message_get_call_id(p_event->request);
                if(pt_callid_ != nullptr){
                    fprintf(stdout, "EXOSIP_MESSAGE_NEW call is number is %s, host is %s\n", pt_callid_->number, pt_callid_->host);
                }

                Cmd_Header *p_cmd = nullptr;
                bool b_parse = osip_message_parse_xml_body(p_msg_body->body, p_cmd);
                if(b_parse && p_cmd != nullptr){
                    if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "Catalog")){
                        //此处需要固化存储,当前只存储到了内存
                        Catalog_Response *pst_response_catalog = (Catalog_Response *)p_cmd;
                        set_catalog_info(pst_response_catalog->m_str_device_id, *pst_response_catalog);
                        set_basic_info_by_catalog(pst_response_catalog->m_str_device_id, *pst_response_catalog);

                        mo_catalog_callback_mutex.lock();
                        if(mp_catalog_cb_func != nullptr){
                            mp_catalog_cb_func(pst_response_catalog->m_str_device_id.c_str(), *pst_response_catalog, mp_catalog_cb_user);
                        }
                        mo_catalog_callback_mutex.unlock();
#ifdef DEBUG_TEST
                        std::string str_channel_id = pst_response_catalog->st_channel_vec[0].str_device_channel_id;
                        //测试:实时视频请求
                        post_invite_play(pst_response_catalog->m_str_device_id, str_channel_id);

                        //std::string str_start_time = "2025-07-18T09:00:00";
                        //std::string str_end_time = "2025-07-18T15:00:00";
                        //post_request_recordinfo(pst_response_catalog->m_str_device_id, str_start_time, str_end_time);

                        //std::string str_playback_start_time = "1752805823";
                        //std::string str_playback_end_time = "1752809025";
                        //post_invite_playback(pst_response_catalog->m_str_device_id, str_channel_id, str_playback_start_time, str_playback_end_time);
#endif
                        delete pst_response_catalog;
                        pst_response_catalog = nullptr;
                    } else if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "DeviceInfo")){
                        DeviceInfo_Response *pst_response_deviceinfo = (DeviceInfo_Response *)p_cmd;
                        mo_device_info_callback_mutex.lock();
                        if(mp_device_info_cb_func != nullptr){
                            mp_device_info_cb_func(pst_response_deviceinfo->m_str_device_id.c_str(), *pst_response_deviceinfo, mp_device_info_cb_user);
                        }
                        mo_device_info_callback_mutex.unlock();
                        delete pst_response_deviceinfo;
                        pst_response_deviceinfo = nullptr;
                    } else if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "DeviceStatus")){
                        DeviceStatus_Response *pst_response_devicestatus = (DeviceStatus_Response *)p_cmd;
                        mo_device_status_callback_mutex.lock();
                        if(mp_device_status_cb_func != nullptr){
                            mp_device_status_cb_func(pst_response_devicestatus->m_str_device_id.c_str(), *pst_response_devicestatus, mp_device_status_cb_user);
                        }
                        mo_device_status_callback_mutex.unlock();
                        delete pst_response_devicestatus;
                        pst_response_devicestatus = nullptr;
                    } else if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "PresetQuery")){
                        PresetList_Response *pst_response_presetlist = (PresetList_Response *)p_cmd;
                        mo_preset_list_callback_mutex.lock();
                        if(mp_preset_list_cb_func != nullptr){
                            mp_preset_list_cb_func(pst_response_presetlist->m_str_device_id.c_str(), *pst_response_presetlist, mp_preset_list_cb_user);
                        }
                        mo_preset_list_callback_mutex.unlock();
                        delete pst_response_presetlist;
                        pst_response_presetlist = nullptr;
                    } else if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "RecordInfo")){
                        RecordInfo_Response *pst_response_recordinfolist = (RecordInfo_Response *)p_cmd;
                        mo_record_info_callback_mutex.lock();
                        if(mp_record_info_cb_func != nullptr){
                            mp_record_info_cb_func(pst_response_recordinfolist->m_str_device_id.c_str(), *pst_response_recordinfolist, mp_record_info_cb_user);
                        }
                        mo_record_info_callback_mutex.unlock();
                        delete pst_response_recordinfolist;
                        pst_response_recordinfolist = nullptr;
                    } else if(0 == strcmp(p_cmd->m_str_cmd_type.c_str(), "MediaStatus")){
                        MediaStatus_Notify *pst_notify = (MediaStatus_Notify *)p_cmd;
                        int i_type = atoi(pst_notify->str_notify_type.c_str());
                        delete pst_notify;
                        pst_notify = nullptr;

                        //121-播放完成/122-播放中断/213-设备报警
                        osip_call_id *pt_callid_ = osip_message_get_call_id(p_event->request);
                        if(pt_callid_ != nullptr){
                            fprintf(stdout, "EXOSIP_MESSAGE_NEW MediaStatus call is number is %s, host is %s\n", pt_callid_->number, pt_callid_->host);
                            std::string str_call_id = pt_callid_->number;
                            if(i_type == 121){
                                del_invite_realtime_cmdplay(str_call_id);
                                del_invite_playback_cmdplay(str_call_id);
                                del_invite_download_cmdplay(str_call_id);
                            }
                        }
                    }
                }
            } else if( MSG_IS_REGISTER(p_event->request) ){
                //接收到下级注册, todo
                osip_authorization_t *auth = nullptr;
                osip_message_get_authorization(p_event->request, 0, &auth);

                if(auth == nullptr){
                    eXosip_lock(mp_ectx_equipment);
//                    eXosip_clear_authentication_info(mp_ectx_equipment);
//                    eXosip_add_authentication_info(
//                        mp_ectx_equipment,
//                        username,         // 设备ID（用户名）
//                        str_sip_domain.c_str(), // Realm（通常与SIP域相同）
//                        str_passwd.c_str(),     // 密码
//                        "MD5",             // 算法
//                        NULL               // 其他参数
//                    );

                    send_unauthorized_response(mp_ectx_equipment, p_event->tid, str_sip_domain);
                    eXosip_unlock(mp_ectx_equipment);
                } else {
                    std::string str_auth_username(auth->username);
                    std::string str_auth_realm(auth->realm);
                    std::string str_auth_uri(auth->uri);
                    std::string str_auth_sip_method(sip_method);
                    std::string str_auth_nonce(auth->nonce);
                    std::string str_auth_response(auth->response);
                    if(!str_auth_username.empty() && (str_auth_username.front() == '\"') && (str_auth_username.back() == '\"')){
                        str_auth_username.erase(str_auth_username.begin());
                        str_auth_username.erase(str_auth_username.end() - 1);
                    }
                    if(!str_auth_realm.empty() && (str_auth_realm.front() == '\"') && (str_auth_realm.back() == '\"')){
                        str_auth_realm.erase(str_auth_realm.begin());
                        str_auth_realm.erase(str_auth_realm.end() - 1);
                    }
                    if(!str_auth_uri.empty() && (str_auth_uri.front() == '\"') && (str_auth_uri.back() == '\"')){
                        str_auth_uri.erase(str_auth_uri.begin());
                        str_auth_uri.erase(str_auth_uri.end() - 1);
                    }
                    if(!str_auth_sip_method.empty() && (str_auth_sip_method.front() == '\"') && (str_auth_sip_method.back() == '\"')){
                        str_auth_sip_method.erase(str_auth_sip_method.begin());
                        str_auth_sip_method.erase(str_auth_sip_method.end() - 1);
                    }
                    if(!str_auth_nonce.empty() && (str_auth_nonce.front() == '\"') && (str_auth_nonce.back() == '\"')){
                        str_auth_nonce.erase(str_auth_nonce.begin());
                        str_auth_nonce.erase(str_auth_nonce.end() - 1);
                    }
                    if(!str_auth_response.empty() && (str_auth_response.front() == '\"') && (str_auth_response.back() == '\"')){
                        str_auth_response.erase(str_auth_response.begin());
                        str_auth_response.erase(str_auth_response.end() - 1);
                    }

                    std::string str_src = str_auth_username +":" + str_auth_realm + ":"+str_passwd;
                    QString qstr_A1 = QCryptographicHash::hash(QString::fromStdString(str_src).toLatin1(), QCryptographicHash::Md5).toHex();
                    std::string str_A1 = qstr_A1.toStdString();

                    str_src = str_auth_sip_method +":" + str_auth_uri;
                    QString qstr_A2 = QCryptographicHash::hash(QString::fromStdString(str_src).toLatin1(), QCryptographicHash::Md5).toHex();
                    std::string str_A2 = qstr_A2.toStdString();

                    str_src = str_A1 + ":" + str_auth_nonce + ":" + str_A2;
                    QString qstr_response = QCryptographicHash::hash(QString::fromStdString(str_src).toLatin1(), QCryptographicHash::Md5).toHex();
                    std::string str_response = qstr_response.toStdString();

                    //osip_message_get_header接口有问题，无法遍历所有头数据，使用osip_message_header_get_byname代替
                    osip_header_t *expires_head = nullptr;
                    int i_expires = 0;
                    int i_ret = 0;
                    i_ret = osip_message_header_get_byname(p_event->request, "Expires", 0, &expires_head);
                    if((expires_head != NULL) && (expires_head->hname != NULL) && strcasecmp(expires_head->hname, "expires") == 0 && (expires_head->hvalue != NULL)){
                        i_expires = atoi(expires_head->hvalue);                        
                    }
                    fprintf(stdout, "----------------i_expires is %d\n", i_expires);

                    if(i_expires != 0){
                        if(str_response != str_auth_response){
                            eXosip_lock(mp_ectx_equipment);
                            send_unauthorized_response(mp_ectx_equipment, p_event->tid, str_sip_domain);
                            eXosip_unlock(mp_ectx_equipment);

                            printf("设备 %s 注册失败\n", username);
                            break;
                        }
                    }

                    osip_header_t *header = nullptr;
                    osip_message_get_header(p_event->request, 0, &header);

                    eXosip_lock(mp_ectx_equipment);
                    //eXosip_default_action(mp_ectx_equipment, p_event);
                    //eXosip_automatic_action( mp_ectx_equipment );
                    // 自动验证（eXosip内部完成哈希计算和比对）
                    osip_message_t *resp;
                    eXosip_message_build_answer(mp_ectx_equipment, p_event->tid, 200, &resp);
                    if(i_expires != 0){
                        osip_message_set_header(resp, "Expires", "3600"); // 设置有效期

                        time_t now = time(NULL);
                        struct tm *gmt = localtime(&now);
                        char date_buf[64];
                        strftime(date_buf, sizeof(date_buf), "%Y-%m-%dT%H:%M:%S", gmt);
                        osip_message_set_header(resp, "Date", date_buf);
                    }
                    eXosip_message_send_answer(mp_ectx_equipment, p_event->tid, 200, resp);
                    eXosip_unlock(mp_ectx_equipment);

                    if(i_expires != 0){
                        printf("设备 %s 注册成功\n", username);

                        add_register_dev(str_username);
                        //服务器需要持久化注册信息，哪怕是服务器重启，对应的设备也无须重新注册可直接做协议交互,待做Todo

                        //osip_uri_t *pst_uri = osip_message_get_uri(p_event->request);
                        //获取catalog
                        osip_from_t *pst_from = osip_message_get_from(p_event->request);
                        //std::string str_to = std::string(pst_from->url->scheme) + ":" + std::string(pst_from->url->username) + "@" + std::string(pst_from->url->host);
                        std::string str_to = std::string(pst_from->url->scheme) + ":" + std::string(pst_from->url->username) + "@" + str_sip_domain;
                        std::string str_device_id = std::string(pst_from->url->username);

                        std::string str_device_ip("");
                        unsigned int ui_device_port = 0;
                        get_dev_ip_from_msg(p_event->request, str_device_ip, ui_device_port);

                        std::string str_from = "sip:" + str_sip_id + "@" + str_sip_domain;

                        st_req_basicinfo st_info;
                        strncpy(st_info.pc_from, str_from.c_str(), str_from.length());
                        strncpy(st_info.pc_to, str_to.c_str(), str_to.length());
                        strncpy(st_info.pc_device_channel_id, str_device_id.c_str(), str_device_id.length());
                        strncpy(st_info.pc_dev_ip, str_device_ip.c_str(), str_device_ip.length());
                        st_info.ui_dev_port = ui_device_port;
                        set_basic_info(str_device_id, st_info);

                        //发送Catalog请求
                        post_request_catalog(str_device_id);

                        //post_request_deviceinfo(str_device_id);
                        //post_request_devicestatus(str_device_id);
                        //post_request_presetlist(str_device_id);
                        //post_control_ptz(str_device_id, 3);
                        //post_control_ptz_preset(str_device_id, 3, 8);
                        //post_control_visual_zoom(str_device_id, 2);
                        //post_control_visual_focus_iris(str_device_id, 2);

                        //std::string str_start_time = "2025-07-09T12:00:00";
                        //std::string str_end_time = "2025-07-09T126:00:00";
                        //post_request_recordinfo(str_device_id, str_start_time, str_end_time);

                        //post_control_teleboot(str_device_id);
                        //post_request_configdownload(str_device_id);
                        //post_control_guard(str_device_id, 1);                        
                    } else {
                        printf("设备 %s 注销成功\n", username);
                        del_register_dev(str_username);
                    }

                    mo_register_callback_mutex.lock();
                    if(mp_register_cb_func != nullptr){
                        mp_register_cb_func(str_username.c_str(), i_expires, mp_register_cb_user);
                    }
                    mo_register_callback_mutex.unlock();
                }
            } else {
                printf( "not support yet!\n" );
            }

            break;
        }
        case EXOSIP_MESSAGE_ANSWERED:
        {
            if(p_event->response != nullptr){
                fprintf(stdout, "##############################EXOSIP_MESSAGE_ANSWERED response recv %d %s\n",
                        p_event->response->status_code, p_event->response->reason_phrase);

                // 获取响应中的 body
                osip_body_t *p_body = NULL;
                osip_message_get_body(p_event->response, 0, &p_body);
                if (p_body && p_body->body) {
                    fprintf(stdout, "##############################Response Body:\n%s\n", p_body->body);
                }
            } else {
                fprintf(stdout, "##############################No response received in ANSWERED event.\n");
            }
            break;
        }            
        case EXOSIP_SUBSCRIPTION_NOTIFY:
        {
            fprintf(stdout, "##############################EXOSIP_SUBSCRIPTION_NOTIFY\n");
            break;
        }
        case EXOSIP_SUBSCRIPTION_ANSWERED:
        {
            if(p_event->response != nullptr){
                fprintf(stdout, "##############################EXOSIP_SUBSCRIPTION_ANSWERED response recv %d %s\n",
                        p_event->response->status_code, p_event->response->reason_phrase);

                // 获取响应中的 body
                osip_body_t *p_body = NULL;
                osip_message_get_body(p_event->response, 0, &p_body);
                if (p_body && p_body->body) {
                    fprintf(stdout, "##############################Response Body:\n%s\n", p_body->body);
                }
            } else {
                fprintf(stdout, "##############################No response received in ANSWERED event.\n");
            }
            break;
        }
        case EXOSIP_CALL_MESSAGE_NEW:
        {
            fprintf(stdout, "-------------------------------------------------EXOSIP_CALL_MESSAGE_NEW\n");
            break;
        }
        case EXOSIP_CALL_PROCEEDING:
        {
            fprintf(stdout, "-------------------------------------------------EXOSIP_CALL_PROCEEDING\n");

            char *s;
            size_t len;
            osip_message_to_str(p_event->response, &s, &len);
            fprintf(stdout, "EXOSIP_CALL_PROCEEDING response msg is:\n%s\n", s);

            delete []s;

            break;
        }
        case EXOSIP_CALL_INVITE:
        {
            fprintf(stdout, "-------------------------------------------------EXOSIP_CALL_INVITE\n");
            break;
        }
        case EXOSIP_CALL_CLOSED:
        {
            fprintf(stdout, "-------------------------------------------------EXOSIP_CALL_CLOSED\n");
            break;
        }
        case EXOSIP_CALL_RELEASED:
        {
            fprintf(stdout, "-------------------------------------------------EXOSIP_CALL_RELEASED\n");

            if(p_event->request != nullptr){
                osip_call_id *pt_callid_ = osip_message_get_call_id(p_event->request);
                if(pt_callid_ != nullptr){
                    fprintf(stdout, "EXOSIP_CALL_RELEASED call is number is %s, host is %s\n", pt_callid_->number, pt_callid_->host);
                }
            }

            if(p_event->response != nullptr){
                char *s;
                size_t len;
                osip_message_to_str(p_event->response, &s, &len);
                fprintf(stdout, "EXOSIP_CALL_RELEASED response msg is:\n%s\n", s);
            }

            break;
        }
        case EXOSIP_CALL_ANSWERED:
        {
            char *s;
            size_t len;
            osip_message_to_str(p_event->response, &s, &len);
            fprintf(stdout, "EXOSIP_CALL_ANSWERED response msg is:\n%s\n", s);
            delete []s;
            s = NULL;
            len = 0;
            osip_message_to_str(p_event->request, &s, &len);
            fprintf(stdout, "EXOSIP_CALL_ANSWERED request msg is:\n%s\n", s);
            delete []s;

            osip_body_t *p_msg_body = NULL;
            osip_message_get_body( p_event->request, 0, &p_msg_body );
            fprintf(stdout, "EXOSIP_CALL_ANSWERED request body is:\n%s\n", p_msg_body->body);

            std::string str_ssrc_y("");
            if(p_msg_body->body != nullptr){
                std::string str_body = p_msg_body->body;

                std::string::size_type npos = str_body.find("y=");
                if(npos != std::string::npos){
                    str_ssrc_y = str_body.substr(npos+2);
                    npos = str_ssrc_y.find_first_not_of("0123456789");
                    str_ssrc_y = str_ssrc_y.substr(0, npos);
                }
            }

            sdp_message_t *sdp = nullptr;
            sdp_message_init(&sdp);
            sdp_message_parse(sdp, p_msg_body->body);
            char *name = sdp_message_o_username_get(sdp);

            fprintf(stdout, "EXOSIP_CALL_ANSWERED sdp message o name is %s\n", name);
            std::string str_invite_channel_id(name);

            char *pc_start_time = sdp_message_t_start_time_get(sdp, 0);
            char *pc_stop_time = sdp_message_t_stop_time_get(sdp, 0);
            std::string str_start_time("");
            if(pc_start_time != NULL){
                str_start_time = pc_start_time;
            }
            std::string str_stop_time("");
            if(pc_stop_time != NULL){
                str_stop_time = pc_stop_time;
            }

            char *media_server_ip = sdp_message_o_addr_get( sdp );
            char *media_server_port = sdp_message_m_port_get( sdp, 0 );
            std::string str_server_ip = media_server_ip;
            std::string str_server_port = media_server_port;

            char *pc_session_name = sdp_message_s_name_get(sdp);
            std::string str_session_name(pc_session_name);
            sdp_message_free(sdp);

            osip_call_id *pt_callid_ = osip_message_get_call_id(p_event->request);
            if(pt_callid_ != nullptr){
                fprintf(stdout, "EXOSIP_CALL_ANSWERED call is number is %s, host is %s\n", pt_callid_->number, pt_callid_->host);
            }

            osip_message_t* msg = nullptr;
            int ret = eXosip_call_build_ack(mp_ectx_equipment, p_event->did, &msg);
            if (!ret && msg) {
                eXosip_call_send_ack(mp_ectx_equipment, p_event->did, msg);
            } else {
                fprintf(stdout, "eXosip_call_send_ack error=%d", ret);
            }

            Cmd_Play st_play;
            st_play.m_str_cmd_type = "INVITE";
            //st_play.m_str_seqno
            st_play.m_str_device_id = str_invite_channel_id;
            st_play.mi_cmd_type = Cmd_Type_Play;
            if(str_session_name == "Play"){
                st_play.mi_play_flag = Cmd_Type_Play_Realtime_Ack;
            } else if(str_session_name == "Playback"){
                st_play.mi_play_flag = Cmd_Type_Play_Back_Ack;
            } else if(str_session_name == "Download"){
                st_play.mi_play_flag = Cmd_Type_Play_Download_Ack;
            }
            st_play.m_str_ip = str_server_ip;
            st_play.m_str_port = str_server_port;
            st_play.m_str_starttime = str_start_time;
            st_play.m_str_endtime = str_stop_time;
            st_play.m_str_ssrc = str_ssrc_y;
            st_play.mi_call_id = p_event->cid;
            st_play.mi_play_did = p_event->did;
            st_play.mi_tid = p_event->tid;
            st_play.m_str_callid_value = pt_callid_->number;
            if(pt_callid_->host != NULL){
                st_play.m_str_callid_host = pt_callid_->host;
            }

            //记录cid与did，BYE协议会用到
            if(st_play.mi_play_flag == Cmd_Type_Play_Realtime_Ack){
                set_invite_realtime_cmdplay(st_play.m_str_callid_value, st_play);
            } else if(st_play.mi_play_flag == Cmd_Type_Play_Back_Ack){
                set_invite_playback_cmdplay(st_play.m_str_callid_value, st_play);
            } else if(st_play.mi_play_flag == Cmd_Type_Play_Download_Ack){
                set_invite_download_cmdplay(st_play.m_str_callid_value, st_play);
            }

            fprintf(stdout, "EXOSIP_CALL_ANSWERED cid is %d, did is %d, tid is %d\n", p_event->cid, p_event->did, p_event->tid);

#ifdef DEBUG_TEST
            gstr_call_id = st_play.m_str_callid_value;
#endif

            st_dev_channel_id st_dev;
            mo_invite_mutex.lock();
            std::map<std::string, st_dev_channel_id>::iterator it = mst_callid_to_dev_channel_id.find(st_play.m_str_callid_value);
            if(it != mst_callid_to_dev_channel_id.end()){
                st_dev = it->second;
            }
            mo_invite_mutex.unlock();

            if(!st_dev.str_device_id.empty()){
                mo_invite_callback_mutex.lock();
                if(mp_invite_cb_func != nullptr){
                    mp_invite_cb_func(st_dev.str_device_id.c_str(), st_play.m_str_device_id.c_str(), st_play, mp_invite_cb_user);
                }
                mo_invite_callback_mutex.unlock();
            }

            break;
        }
        default:
        {
            fprintf(stdout, "##########ev_type is %d\n", p_event->type);
            break;
        }
        }
    }
}

bool sip_server::get_dev_ip_from_msg(osip_message_t *pt_message, std::string &str_ip, unsigned int &us_port)
{
    osip_via_t *via = nullptr;
    osip_message_get_via(pt_message, 0, &via);
    if(via && via->host){
        str_ip = std::string(via->host);
        us_port = atoi(via->port);

        //osip_via_free(via);
        return true;
    }

    osip_contact_t *contact = nullptr;
    osip_message_get_contact(pt_message, 0, &contact);
    if(contact && contact->url && contact->url->host){
        str_ip = std::string(contact->url->host);
        us_port = atoi(contact->url->port);

        //osip_contact_free(contact);
        return true;
    }

    return false;
}
